package net.chasing.androidbaseconfig.widget.rich.base;

import android.content.Context;
import android.graphics.Color;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.style.ClickableSpan;
import android.view.View;

import androidx.annotation.NonNull;

import net.chasing.androidbaseconfig.widget.rich.RichTextView;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 富文本解析抽象类
 * 关于Simple和非Simple概念：
 * 以mPattern进行解析，如果解析规则与结果不一样，则为非Simple的RichItem，记录的下标是解析规则的下标
 * Simple的RichItem，记录的下标为结果的下标
 * 例如：解析规则为<a>@XXX</a>   想要的结果是@XXX
 */
public abstract class AbstractRichParser implements IRichParser {
    //富文本对应字体颜色
    protected int mColor = Color.BLUE;

    // 匹配规则，每个实现类都必须在构造器中进行设置
    protected String mPattern;
    // 匹配的隐式label规则，例如：<a>...</a>
    protected String mLabelPattern;
    // 富文本格式规则，例如： @%s  必须使用%s进行占位
    protected String mRichFormat;
    // 要匹配的文本
    protected String mTargetStr;
    // 要匹配的id格式，id必须包含与" "之中
    protected String mIdPattern;

    protected OnRichItemClickListener mOnRichItemClickListener;
    protected final int mCharCountBeforeName = 1;
    protected int mCharCountAfterName = 0;

    public AbstractRichParser setOnRichItemClickListener(OnRichItemClickListener onRichItemClickListener) {
        mOnRichItemClickListener = onRichItemClickListener;
        return this;
    }

    public void setColor(int color) {
        mColor = color;
    }

    @Override
    public int getId(String labelText) {
        Pattern r = Pattern.compile(mIdPattern);
        Matcher m = r.matcher(labelText);
        String target;
        if (m.find()) {
            target = m.group();
            return Integer.parseInt(target.substring(target.indexOf('\"') + 1, target.lastIndexOf('\"')));
        }
        return 0;
    }

    @Override
    public void resetTargetStr(String text) {
        mTargetStr = text;
    }

    @Override
    public String getRichText(String str) {
        return String.format(mRichFormat, str);
    }

    @Override
    public String parserLabelTextToRich(String text) {
        if (!TextUtils.isEmpty(mLabelPattern)) {
            Pattern r = Pattern.compile(mLabelPattern);
            Matcher m = r.matcher(text);
            String target, userName;
            while (m.find()) {
                target = m.group();
                userName = target.substring(target.indexOf('>') + mCharCountBeforeName + 1, target.lastIndexOf('<') - mCharCountAfterName);
                text = text.replace(target, String.format(mRichFormat, userName));
            }
        }
        return text;
    }

    @Override
    public String revertRichItem(String str) {
        return str.substring(2 + mCharCountBeforeName, str.length() - 1 - mCharCountAfterName);
    }

    @Override
    public boolean containsRichItem() {
        if (TextUtils.isEmpty(mTargetStr)) {
            return false;
        }
        Pattern p = Pattern.compile(mPattern);
        Matcher matcher = p.matcher(mTargetStr);
        return matcher.find();
    }

    @Override
    public List<RichItem> getAllRichItem() {
        Pattern r = Pattern.compile(mPattern);
        Matcher m = r.matcher(mTargetStr);
        List<RichItem> richList = new ArrayList<>();
        RichItem richItem;
        while (m.find()) {
            richItem = new RichItem();
            richItem.setRichText(m.group());
            richItem.setStartPosition(m.start());
            richItem.setEndPosition(m.end());
            richList.add(richItem);
        }
        return richList;
    }

    @Override
    public RichItem getSimpleFirstRichItem() {
        if (TextUtils.isEmpty(mTargetStr)) {
            return null;
        }
        Pattern r = Pattern.compile(mPattern);
        Matcher m = r.matcher(mTargetStr);
        if (m.find()) {
            StringBuilder sb = new StringBuilder();
            RichItem changeRichItem = new RichItem();
            sb.append(mTargetStr.substring(0, m.start()));
            changeRichItem.setStartPosition(sb.length());
            changeRichItem.setRichText(parserLabelTextToRich(m.group()));
            sb.append(parserLabelTextToRich(m.group()));
            changeRichItem.setEndPosition(sb.length());
            return changeRichItem;
        }
        return null;
    }

    @Override
    public RichItem getFirstRichItem() {
        if (TextUtils.isEmpty(mTargetStr)) {
            return null;
        }
        Pattern r = Pattern.compile(mPattern);
        Matcher m = r.matcher(mTargetStr);
        if (m.find()) {
            RichItem changeRichItem = new RichItem();
            changeRichItem.setRichText(m.group());
            changeRichItem.setStartPosition(m.start());
            changeRichItem.setEndPosition(m.end());
            return changeRichItem;
        }
        return null;
    }

    @Override
    public String getFirstRichItemText() {
        if (TextUtils.isEmpty(mTargetStr)) {
            return "";
        }
        Pattern p = Pattern.compile(mPattern);
        Matcher matcher = p.matcher(mTargetStr);

        String result = "";
        if (matcher.find()) {
            result = matcher.group();
        }
        return result;
    }

    @Override
    public int getFirstRichIndex() {
        if (TextUtils.isEmpty(mTargetStr)) {
            return -1;
        }
        String item = getFirstRichItemText();
        if (TextUtils.isEmpty(item)) {
            return -1;
        }
        return mTargetStr.indexOf(item);
    }

    @Override
    public RichItem getSimpleLastRichItem() {
        if (TextUtils.isEmpty(mTargetStr)) {
            return null;
        }
        Pattern r = Pattern.compile(mPattern);
        Matcher m = r.matcher(mTargetStr);
        RichItem changeRichItem = null;
        while (m.find()) {
            changeRichItem = new RichItem();
            changeRichItem.setRichText(m.group());
            changeRichItem.setStartPosition(m.start());
            changeRichItem.setEndPosition(m.end());
        }
        return changeRichItem;
    }

    @Override
    public RichItem getLastRichItem() {
        if (TextUtils.isEmpty(mTargetStr)) {
            return null;
        }
        Pattern r = Pattern.compile(mPattern);
        Matcher m = r.matcher(mTargetStr);
        StringBuilder sb;
        RichItem changeRichItem = null;
        while (m.find()) {
            sb = new StringBuilder();
            changeRichItem = new RichItem();
            sb.append(mTargetStr.substring(0, m.start()));
            changeRichItem.setStartPosition(sb.length());
            changeRichItem.setRichText(parserLabelTextToRich(m.group()));
            sb.append(parserLabelTextToRich(m.group()));
            changeRichItem.setEndPosition(sb.length());
        }
        return changeRichItem;
    }

    @Override
    public String getLastRichItemText() {
        if (TextUtils.isEmpty(mTargetStr)) {
            return "";
        }
        Pattern p = Pattern.compile(mPattern);
        Matcher matcher = p.matcher(mTargetStr);

        String result = "";
        while (matcher.find()) {
            result = matcher.group();
        }
        return result;
    }

    @Override
    public int getLastRichIndex() {
        if (TextUtils.isEmpty(mTargetStr)) {
            return -1;
        }
        String item = getLastRichItemText();
        if (TextUtils.isEmpty(item)) {
            return -1;
        }
        return mTargetStr.lastIndexOf(item);
    }

    @Override
    public SpannableString getRichSpannable(final Context context) {
        StringBuilder sb = new StringBuilder();
        List<RichItem> richList = getAllRichItem();
        List<RichItem> changeRichList = new ArrayList<>();
        RichItem changeRichItem;
        int preRichItemEnd = 0;
        for (RichItem richItem : richList) {
            changeRichItem = new RichItem();
            sb.append(mTargetStr.substring(preRichItemEnd, richItem.getStartPosition()));
            changeRichItem.setStartPosition(sb.length());
            changeRichItem.setRichText(parserLabelTextToRich(richItem.getRichText()));
            sb.append(parserLabelTextToRich(richItem.getRichText()));
            changeRichItem.setEndPosition(sb.length());
            changeRichList.add(changeRichItem);
            changeRichItem.setId(getId(richItem.getRichText()));
            preRichItemEnd = richItem.getEndPosition();
        }
        sb.append(mTargetStr.substring(preRichItemEnd));

        SpannableString spannableString = new SpannableString(sb.toString());
        ClickableSpan clickableSpan;
        for (final RichItem richItem : changeRichList) {
            clickableSpan = new ClickableSpan() {
                @Override
                public void updateDrawState(@NonNull TextPaint ds) {
                    ds.setColor(mColor);
                    ds.setUnderlineText(false);
                }

                @Override
                public void onClick(@NonNull View view) {
                    if (RichTextView.isLongClick()) {
                        RichTextView.setIsLongClick(false);
                        return;
                    }
                    if (mOnRichItemClickListener != null)
                        mOnRichItemClickListener.onRichItemClick(context, richItem);
                }
            };
            if (spannableString.length() >= richItem.getEndPosition())
                spannableString.setSpan(clickableSpan, richItem.getStartPosition(),
                        richItem.getEndPosition(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
        }
        return spannableString;
    }
}
